package com.partsoft.dits.log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import com.partsoft.dits.EdgeDescriptor;

public class BaseLogEntity implements LogEntity {
	
	private static final long serialVersionUID = -1820273157327342309L;
	
	private String id;
	
	private Class<? extends EdgeDescriptor> descriptorClass;
	
	private Object descriptorIdentity;

	private Date logDate;
	
	private LogType type;
	
	private LogLevel level;
	
	private String lineNumber;
	
	private String content;
	
	private String fileName;
	
	private String className;
	
	private String methodName;
	
	private String threadName;
	
	private List<LogAttachment> attachments;
	
	public Class<? extends EdgeDescriptor> getDescriptorClass() {
		return descriptorClass;
	}

	public void setDescriptorClass(Class<? extends EdgeDescriptor> descriptorClass) {
		this.descriptorClass = descriptorClass;
	}

	public Object getDescriptorIdentity() {
		return descriptorIdentity;
	}

	public void setDescriptorIdentity(Object descriptorIdentity) {
		this.descriptorIdentity = descriptorIdentity;
	}

	public Date getLogDate() {
		return logDate;
	}

	public void setLogDate(Date logDate) {
		this.logDate = logDate;
	}

	public LogType getType() {
		return type;
	}

	public void setType(LogType type) {
		this.type = type;
	}

	public LogLevel getLevel() {
		return level;
	}

	public void setLevel(LogLevel level) {
		this.level = level;
	}

	public String getLineNumber() {
		return lineNumber;
	}

	public void setLineNumber(String lineNumber) {
		this.lineNumber = lineNumber;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public LogAttachment[] getAttachments() {
		return attachments == null ? new LogAttachment[0] : attachments.toArray(new LogAttachment[0]);
	}
	
	public void setAttachments(LogAttachment []logAttachments) {
		if (logAttachments == null || logAttachments.length == 0) {
			this.attachments = null;
		} else {
			attachments = new ArrayList<LogAttachment>(Arrays.asList(logAttachments));
		}
	}

	public void setAttachments(List<LogAttachment> logAttachments) {
		if (logAttachments == null || logAttachments.size() == 0) {
			this.attachments = null; 
		} else {
			this.attachments = new ArrayList<LogAttachment>(logAttachments);
		}
	}
	
	public void addAttachment(LogAttachment attachment) {
		Assert.notNull(attachment);
		if (attachments == null) {
			attachments = new ArrayList<LogAttachment>(1);
		}
		attachments.add(attachment);
	}
	
	public void removeAttachment(LogAttachment attachment) {
		Assert.notNull(attachment);
		if (attachments != null) {
			attachments.remove(attachment);
			if (attachments.size() == 0) attachments = null;
		}
	}
	
	public boolean hasAttachments() {
		return attachments != null && attachments.size() > 0;
	}
	
	public boolean hasAttachment(String name) {
		boolean result = hasAttachments();
		if (result) {
			result = false;
			for (LogAttachment logattr : attachments) {
				if (ObjectUtils.nullSafeEquals(name, logattr.getName())) {
					result = true;
					break;
				}
			}
		}
		return result;
	}

	public LogAttachment getAttachment(String name) {
		Assert.isTrue(hasAttachment(name));
		LogAttachment result = null;
		for (LogAttachment logattr : attachments) {
			if (ObjectUtils.nullSafeEquals(name, logattr.getName())) {
				result = logattr;
				break;
			}
		}
		Assert.notNull(result);
		return result;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public String getThreadName() {
		return threadName;
	}

	public void setThreadName(String threadName) {
		this.threadName = threadName;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	@Override
	public String toString() {
		return "BaseLogEntity [id=" + id + ", descriptorClass="
				+ descriptorClass + ", descriptorIdentity="
				+ descriptorIdentity + ", logDate=" + logDate + ", type="
				+ type + ", level=" + level + ", lineNumber=" + lineNumber
				+ ", content=" + content + ", fileName=" + fileName
				+ ", className=" + className + ", methodName=" + methodName
				+ ", threadName=" + threadName + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		BaseLogEntity other = (BaseLogEntity) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public BaseLogEntity clone() {
		try {
			BaseLogEntity clone = (BaseLogEntity) super.clone();
			if (attachments != null) {
				List<LogAttachment> cloneAtts = new LinkedList<LogAttachment>();
				for (LogAttachment att : attachments) {
					cloneAtts.add(att.clone());
				}
				clone.attachments = new ArrayList<LogAttachment>(cloneAtts);
			}
			return clone;
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}
}
